package edu.bbu.cshu.wmpc.formalization;

import java.util.ArrayList;

import edu.bbu.cshu.wmpc.core.LevelTypes;
import edu.bbu.cshu.wmpc.core.SourceCodeWmpc;

/**
 * <ul>
 * <li><b><i>Formalization</i></b></li>
 * <li style="list-style: none;"></li>
 * <li style="list-style: none;">
 * Abstract class that is to be extended by classes that perform code formalization.
 * 
 * @author WMPC team
 * </li>
 * </ul>
 */

public abstract class Formalization {	
	
	/**
	 * <ul>
	 * <li><b><i>source</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * {@link SourceCodeWmpc} that contains the source code which will be formalized
	 * </li>
	 * </ul>
	 */
	protected SourceCodeWmpc source;

	/**
	 * <ul style="margin-top: 24px;">
	 * <li><b><i>removeComments</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract void removeComments()}</p>
	 * <br>
	 * Comments will be removed from the {@code source}.
	 * </li>
	 * </ul>
	 */
	protected abstract void removeComments();
	
	/**
	 * <ul style="margin-top: 24px;">
	 * <li><b><i>newLineBreaker</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract void newLineBreaker()}</p>
	 * <br>
	 * 
	 * Makes wraps in {@code source} after every ";", puts in new line all instructions which are in common line.
	 * </li>
	 * </ul>
	 */
	protected abstract void newLineBreaker();
	
	/** 
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>removeQuates</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract String removeQuates(}{@link String} {@code str)}</p>
	 * <br>	
	 * Quotes will be removed from the {@code str}.
	 * 
	 * @param str - from this string will be removed the quotes
	 * @return a {@code String} which is without quotes
	 * </li>
	 * </ul>
	 */
	protected abstract String removeQuates(String str);  
	
	/**
	 * <ul style="margin-top: 24px;">
	 * <li><b><i>removeWhitespace</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract} {@link String} {@code removeWhitespace(}{@link String} {@code str)}</p>
	 * <br>	
	 * White spaces will be removed from the string {@code str}.
	 * 
	 * @param str - from this string will be removed the white spaces 
	 * @return a {@code String} which is without white spaces
	 * </li>
	 * </ul>
	 */
	protected abstract String removeWhitespace(String str); 

	/**
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>removeImports</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract} {@link String} {@code removeImports(}{@link String} {@code str)}</p>
	 * <br>	
	 * Imports, all words which have special, predefined syntactic meanings, without roll in the algorithm will be removed from the string {@code str} programming language specific.
	 * 
	 * @param str - from this string will be removed the imports, specific keywords which have no algorithmic roles
	 * @return a {@code String} which is without imports
	 * </li>
	 * </ul>
	 */
	protected abstract String removeImports(String str); 
	
	/**
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>removeInput</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract} {@link String} {@code removeInput(}{@link String} {@code str)}</p>
	 * <br>	
	 * Inputs will be removed from the string {@code str}, programming language specific.
	 * 
	 * @param str - from this string will be removed the inputs
	 * @return a {@code String} which is without inputs
	 * </li>
	 * </ul>
	 */
	protected abstract String removeInput(String str);
	
	/**
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>removeOutput</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract} {@link String} {@code removeOutput(}{@link String} {@code str)}</p>
	 * <br>	
	 * Outputs will be removed from the string {@code str}, programming language specific.
	 * 
	 * @param str - from this string will be removed the outputs
	 * @return a {@code String} which is without outputs
	 * </li>
	 * </ul>
	 */
	protected abstract String removeOutput(String str);
	
	/**
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>removeTryCatch</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract} {@link String} {@code removeTryCatch(}{@link String} {@code str)}</p>
	 * <br>	
	 * Try-catch branches will be removed from the string {@code str}, programming language specific.
	 * 
	 * @param str - from this string will be removed the try-catch branches
	 * @return a {@code String} which is without outputs
	 * </li>
	 * </ul>
	 */
	protected abstract String removeTryCatch(String str);
	
	/**
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>removeBeginEnd</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract} {@link String} {@code removeBeginEnd(}{@link String} {@code str)}</p>
	 * <br>	
	 * "BEGIN", "END" keywords will be replace with {} from the string {@code str}.
	 * 
	 * @param str - from this string will be removed the begin/end part
	 * @return a {@code String} which is without begin/end part
	 * </li>
	 * </ul>
	 */
	protected abstract String removeBeginEnd(String str);
	
	/**
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>handleVariables</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract} {@link String} {@code handleVariables(}{@link String} {@code str)}</p>
	 * <br>	
	 * Handles the variables' name in declarations, assignments, repetitive structures, if/switch-case branches in the string {@code str}, makes them uniform.
	 * 
	 * @param str -  variables from this {@code String} will be handled and uniformed
	 * @return a {@code String} which is with uniform variables
	 * </li>
	 * </ul>
	 */
	protected abstract String handleVariables(String str);
	
	/**
	  * <ul style="margin-top: 24px;">
	 * <li><b><i>shortenVariables</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code protected abstract} {@link String} shortenVariables(}{@link String} str)}</p>
	 * <br>	
	 * If the variables' name are too long it shortens them to four characters. 
	 * 
	 * @param str - from this string will be the variables' name shorten
	 * @return a {@code String} which is with short name of variables
	 * </li>
	 * </ul>
	 */
	protected abstract String shortenVariables(String str);

	
	/**
	 * <ul style="margin-top: 24px;">
	 * <li><b><i>executeTest</i></b></li>
	 * <li style="list-style: none;"></li>
	 * <li style="list-style: none;">
	 * <p style="margin-left: 7px;">{@code public} {@link SourceCodeWmpc} {@code executeFormalization(}{@link LevelTypes} {@code level)}</p>
	 * <br>	
	 * Executes formalization on {@code source} depending on the specified {@code level}.
	 *  
	 * @param level - specifies the level of the test to be performed
	 * @return an {@code SourceCodeWmpc} containing the formalized source code
	 * </li>
	 * </ul>
	 */
	public SourceCodeWmpc executeFormalization(LevelTypes level) {
		switch (level) {
			case ORIGINAL:
				removeComments();
			case MODIFIED: 
				removeComments();
				newLineBreaker();
				String tmp;
				int size = source.getModified().size();
				ArrayList<String> modified = new ArrayList<String>();
				for (int i = 0; i < size; i++) {
					tmp = source.getModified().get(i);
					tmp = removeQuates(tmp);
					tmp = removeWhitespace(tmp);
					tmp = removeImports(tmp);
					tmp = removeOutput(tmp);
					tmp = removeInput(tmp);
					tmp = removeTryCatch(tmp);
					tmp = removeBeginEnd(tmp);
					//tmp = handleVariables(tmp);
					tmp = shortenVariables(tmp);
					modified.add(tmp);
				}
				source.setModified(modified);
				break;
		}
		return source;
	}
}